<template>
    <view class="image-upload">
        <view
            v-for="(item, index) in imgList"
            :key="index"
            class="up-box-1"
        >
            <image
                class="uped-img"
                :src="imgFilter(item)"
                mode="scaleToFill"
                @click="previewImage(index)"
            />
            <view
                v-show="!readOnly"
                class="delete-img"
                @click="deleteImg(index)"
            />
        </view>
        <view
            v-if="!readOnly && imgList.length < limit"
            class="up-box"
        >
            <view
                class="image-upload-input"
                @click="chooseImage"
            />
        </view>
    </view>
</template>

<script setup name="ImageUploader">
    import { ref, reactive, toRefs, watch, inject } from 'vue';
    import { Toast } from '@/tools/util';

    const props = defineProps({
        // 最大上传图片数
        limit: {
            type: Number,
            default: 1
        },
        // 默认图片数组
        imageList: {
            type: Array,
            default: () => []
        },
        readOnly: { // 是否只读
            type: Boolean,
            default: false
        },
        gzip: { // 是否开启图片压缩
            type: Boolean,
            default: true
        },
        sourceType: { // 上传类型，相册/拍照
            type: Array,
            default: () => ['album', 'camera']
        },
        extData: { // 图片上传携带额外参数
            type: Object,
            default: () => ({})
        },
        /* 系统上传接口地址
            https://yq.zsacloud.zhonshian.com/dev-asian-api/fileupload/file/uploadImages
            https://yq.zsacloud.zhonshian.com/zsaImg/fastDfs/uploadFast
        */
        uploadUrl: {
            type: String,
            default: import.meta.env.VITE_IMG_UPLOAD_URL + '/fastDfs/uploadFast',
        }
    });

    const emit = defineEmits(['getImg']);

    const $api = inject("$api");

    let state = reactive({
        imgList: props.imageList
    });

    const {imgList} = toRefs(state);

    watch(
        () => props.imageList,
        () => {
            state.imgList = props.imageList;
        }, {
            deep: true,
            immediate: true
        }
    );

    // 格式化图片
    const imgFilter = (val) => {
        if (val) {
            return import.meta.env.VITE_IMG_BASE_URL + val;
        }
    };

    // 上传图片调用方法
    const chooseImage = () => {
        // 判断已上传图片数是否达到限制
        if (state.imgList.length > props.limit) {
            Toast('最多上传' + props.limit + '张图片');
            return;
        }

        // 定义压缩参数
        let sizeType = ['original'];

        // 定义上传可选择图片数count
        let count = props.limit - state.imgList.length;
        // #ifdef  H5
        count = count > 1 ? 1 : count;
        // #endif

        // #ifdef  MP-WEIXIN
        if (props.gzip) { // 判断是否需要压缩
            sizeType = ['compressed'];
        }
        // #endif

        // 调用图片上传api
        uni.chooseImage({
            sourceType: props.sourceType,
            sizeType: sizeType,
            count: count,
            success: (imgRes) => {
                uni.showLoading({
                    title: '上传中',
                    mask: true
                });

                // 存储临时图片文件/路径
                let arr = [];

                //#ifdef MP-WEIXIN
                for (let item of imgRes.tempFilePaths) {
                    arr.push({
                        path: item
                    });
                }
                //#endif

                //#ifdef H5
                for (let file of imgRes.tempFiles) {
                    // 判断是否图片文件
                    if (file.type.indexOf('image/') == -1) {
                        uni.hideLoading();
                        Toast('请选择图片文件上传！');
                        return;
                    }
                    arr.push({
                        path: file // 图片文件
                    });
                }
                //#endif

                // 循环上传图片
                uploadAll(arr);
            }
        });
    };

    // 循环调用图片上传接口
    const uploadAll = (files) => {
        let promises = [];
        for (let file of files) {
            let uploadPromise = new Promise((resolve, reject) => {
                //#ifdef MP-WEIXIN
                upLoadImage(file.path, (img) => {
                    resolve(img);
                }, (err) => {
                    reject(err);
                    console.log(err);
                });
                //#endif

                //#ifdef H5
                if (props.gzip) {
                    compressImage(file.path).then(imgRes => {
                        upLoadImage(imgRes, (img) => {
                            resolve(img);
                        }, (err) => {
                            reject(err);
                            console.log(err);
                        });
                    }).catch(err => {

                    });
                } else {
                    upLoadImage(file.path, (img) => {
                        resolve(img);
                    }, (err) => {
                        reject(err);
                        console.log(err);
                    });
                }
                //#endif
            });
            promises.push(uploadPromise);
        }
        Promise.all(promises).then(values => {
            uni.hideLoading();
            state.imgList = state.imgList.concat(values);
            emit('getImg', state.imgList);
        }).catch(err => {
            uni.hideLoading();
            console.log(err);
        });
    };

    // H5端压缩图片
    const compressImage = (file) => {
        return new Promise((resolve, reject) => {
            let size = file.size / 1024 / 1024;
            let quality = 1;
            if (size > 0.1 && size < 0.5) {
                quality = 80;
            } else if (size >= 0.5 && size < 1) {
                quality = 50;
            } else {
                quality = 10;
            }
            // 创建一个HTML5的FileReader对象
            let reader = new FileReader();
            reader.onerror = (e) => {
                reject(e);
            };
            //创建一个img对象
            let img = new Image();
            img.onerror = (e) => {
                reject(e);
            };
            let filename = file.name;
            if (file) {
                reader.readAsDataURL(file);
            }
            reader.onload = (e) => {
                let base64Str = reader.result.split(',')[1];
                img.src = e.target.result;
                // base64地址图片加载完毕后执行
                img.onload = function() {
                    // 缩放图片需要的canvas（也可以在DOM中直接定义canvas标签，这样就能把压缩完的图片不转base64也能直接显示出来）
                    let canvas = document.createElement('canvas');
                    let context = canvas.getContext('2d');
                    //对图片进行缩放
                    canvas.width = this.width;
                    canvas.height = this.height;
                    // 清除画布
                    context.clearRect(0, 0, this.width, this.height);
                    // 图片压缩
                    context.drawImage(img, 0, 0, this.width, this.height);
                    /*第一个参数是创建的img对象；第二三个参数是左上角坐标，后面两个是画布区域宽高*/
                    //压缩后的base64文件
                    canvas.toBlob(
                        blobs => {
                            resolve(blobs);
                        },
                        'image/jpeg',
                        quality
                    );
                };
            };
        });
    };

    // 图片上传post请求
    const upLoadImage = async (file, success, fail) => {
        let obj = {
            url: props.uploadUrl,
            name: 'file',
            formData: Object.assign({groupType: 'personalInfo'}, props.extData),
            header: {
                // "Content-Type": "multipart/form-data;charset=utf-8"
            },
            timeout: 30000,
            success: (res) => {
                let data = JSON.parse(res.data);
                if (data.code == 10000) {
                    success(data.data);
                } else {
                    fail(data);
                    Toast(data.msg);
                }
            },
            fail: (res) => {
                fail(res);
                Toast('上传失败！');
            }
        };

        //#ifdef MP-WEIXIN
        obj.filePath = file;
        //#endif

        //#ifdef H5
        obj.file = file;
        //#endif

        uni.uploadFile(obj);
    };

    // 图片预览
    const previewImage = (index) => {
        let imgs = [];
        for (let img of state.imgList) {
            imgs.push(IMG_BASE_URL + img);
        }
        uni.previewImage({
            urls: imgs,
            current: index
        });
    };

    // 删除图片
    const deleteImg = (index) =>{
        uni.showModal({
            title: '提示',
            content: '确定删除图片？',
            success: (res) => {
                if (res.confirm) {
                    state.imgList.splice(index, 1);
                    emit('getImg', state.imgList);
                } else if (res.cancel) {
                    console.log('用户点击取消');
                }
            },
            fail: () => {

            }
        });
    };
</script>

<style lang="less" scoped>
    .image-upload {
        width: 100%;
        height: auto;
        background: #ffffff;
        display: flex;
        justify-content: flex-start;
        align-items: flex-start;
        flex-wrap: wrap;
    }

    .up-box-1 {
        width: 180rpx;
        height: 180rpx;
        border-radius: 4px;
        margin-bottom: 10rpx;
        margin-right: 20rpx;
        position: relative;

        .uped-img {
            width: 180rpx;
            height: 180rpx;
            background: url(~@/static/image/upload/icon_error.png) center no-repeat;
            background-size: 64rpx 64rpx;
        }

        .delete-img {
            width: 32rpx;
            height: 32rpx;
            background: url(~@/static/image/upload/icon_delete.png) 8rpx 0 no-repeat;
            background-size: 24rpx 24rpx;
            background-color: #f56c6c;
            border-bottom-left-radius: 32rpx;
            position: absolute;
            top: 0rpx;
            right: 0rpx;
        }
    }

    .up-box {
        width: 180rpx;
        height: 180rpx;
        background: url(~@/static/image/upload/icon_upload.png) center no-repeat;
        background-size: 64rpx 64rpx;
        background-color: #F8F8F8;
        position: relative;

        .image-upload-input {
            width: 180rpx;
            height: 180rpx;
            position: absolute;
            top: 0;
            left: 0;
            z-index: 99;
        }
    }
</style>
